/**
 * @file
 * Settings window header file.
 *
 * Kisa provides spell checking as you type and displays the result in a small
 * window on your Desktop.
 *
 * Copyright (c) 2009 by Pete Black <theblackpeter@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * @author Pete Black <theblackpeter@gmail.com>
 */
#ifndef KISASETTINGS_H
#define KISASETTINGS_H

#include <QDialog>
#include <QSettings>

class KisaLib;

#include "ui_kisasettings.h"

/**
 * @class KisaSettings
 * The KisaSettings class provides a graphical interface to access and update
 * the application settings. There is both a top-level dialog window for
 * changing the application settings, and functions that provide easy access to
 * theses setting.
 *
 * A modal dialog with default buttons is used. Also, icons from the current
 * icon theme are used whenever available.
 *
 * @image html general.png "Kisa general application settings"
 * @image html appearance.png "Kisa appearance settings"
 * @image html extras.png "Kisa extras settings"
 *
 * @note Make sure KisaLib has been initialized before instantiating this class.
 *
 * @author Pete Black <theblackpeter@gmail.com>
 * @see Kisa
 */
class KisaSettings : public QDialog, public Ui::KisaSettings {
  Q_OBJECT

  public:
  /**
   * Constructor. The member values are set here, acquired from the settings
   * file, "~/.config/kisa/kisa.conf". If no such file exists then the default
   * values are used.
   *
   * @param parent pointer to the the parent widget
   * @param fl set of window flags conjoined using the bitwise logical
   * manipulator OR, "|"
   */
  KisaSettings(QWidget* parent = NULL, Qt::WFlags fl = 0);

  /**
   * Destructor.
   */
  virtual ~KisaSettings();

  /**
   * Adds the selected word from the pop-up to the desktop's clipboard.
   *
   * @image html copy_to_clipboard.png "The copy suggestion to clipboard option"
   *
   * @return the current value
   */
  bool addToClipboard() const { return checkBox_9->isChecked(); }

  /**
   * Creates a Regular Expression string of the items in the list. Each item
   * is separated by a "|" and the string is enclosed in "()". This string can
   * then later be used to match and ignore the windows when parsing the
   * window names for subscription.
   *
   * @return the string in Regular Expression format. For example, a list with
   * @c N "names" would look like this: "(name1|name2|...|nameN)"
   */
  const QString createRegExpString();

  /**
   * Returns the custom command that is specified in the settings.
   *
   * @image html custom_command.png "The custom command setting"
   *
   * @return the current custom command
   */
  const QString customCommand() const { return lineEdit_3->text(); }

  /**
   * Returns the custom command icon that is specified in the settings. Used
   * in the context menu of the text field in the main widget window.
   *
   * @see customCommand()
   *
   * @return the current custom command icon
   */
  const QIcon customCommandIcon() const { return toolButton->icon(); }

  /**
   * Gets the custom command name that is specified in the settings. Used in
   * the context menu of the text field in the main widget window.
   *
   * @image html kisa_context_menu.png "The custom command name in the text field's context menu"
   *
   * @see customCommand()
   *
   * @return the current custom command name
   */
  const QString customCommandName() const { return lineEdit_2->text(); }

  /**
   * Returns the position of the current dictionary in the dictionaries list.
   *
   * @return the current index value
   */
  int dictionaryIndex() const { return comboBox_2->currentIndex(); }

  /**
   * Gets the desired font for the main window widget. Font family, style
   * (bold or italic) and font size may be set. Any system fonts is available.
   *
   * @image html font_combo_box.png "Font type selection"
   *
   * @return the current value
   */
  QFont font() const { return m_font; }

  /**
   * Returns a list of window names that are ignored when parsing the window
   * names for subscription notification. Any window in this list will not
   * receive any event subscription.
   *
   * @image html ignore_list.png "The ignore list settings"
   *
   * @return the current value
   */
  QStringList ignoreList() const { return m_ignoreList; }

  /**
   * Gets a regular expression representation of the ignore list. Each item
   * is separated by a "|" and the string is enclosed in "()". This string can
   * then later be used to match and ignore the windows when parsing the
   * window names for subscription.
   *
   * For example, a list with N "names" would look like this:
   * "(name1|name2|...|nameN)"
   *
   * Default value is "(kickoff|kwin|toolbar)".
   *
   * @return the current value
   */
  QString ignoreListRegExp() { return createRegExpString(); }

  /**
   * Checks whether the application should replace the last typed word in
   * the client window with the one selected from the pop-up. If @c true, then
   * the selected word from the pop-up will be sent back to
   * the originating window, otherwise not.
   *
   * Default is @c false.
   *
   * @image html replace_in_client.png "The replace in client option"
   *
   * @return the current value
   */
  bool replaceInClient() const { return checkBox_11->isChecked(); }

  /**
   * Sets the position of the current dictionary in the dictionaries list to
   * that given by @p index.
   *
   * @param index the new index value
   */
  void setDictionaryIndex(const int index) { comboBox_2->setCurrentIndex(index); }

  /**
   * Checks if a tool button should be used to display current dictionary
   * information next to the text field in the main widget window. If @c true
   * it will, otherwise not.
   *
   * @image html show_button.png "The show dictionary info button option"
   * @image html kisa_widget_button.png "Dictionary language button displayed in the main widget window"
   * @image html kisa_widget_no_button.png "The main widget window with no language button"
   *
   * Default is @c true.
   *
   * @return the current value
   */
  bool showButton() const { return checkBox_14->isChecked(); }

  /**
   * Checks if a country flag representing the language of the current
   * dictionary in use should be displayed next to the text field in the main
   * widget window. If @c true it will, otherwise the language code of
   * the current dictionary will be displayed instead.
   *
   * @image html show_flag.png "The show dictionary country flag option"
   * @image html kisa_widget.png "The dictionary language country flag in the main widget window"
   * @image html kisa_widget_no_flag.png "The main widget window with no country flag icon"
   *
   * Default is @c true.
   *
   * @return the current value
   */
  bool showFlag() const { return checkBox_13->isChecked(); }

  /**
   * Checks whether to show a pop-up containing the possible suggestions
   * whenever a unknown word is encountered. If @c true then it will be shown,
   * otherwise not.
   *
   * Default is @c true.
   *
   * @image html show_popup.png "The show pop-up option"
   * @image html kisa_suggestion_popup.png "Suggestions pop-up list"
   *
   * @return the current value
   */
  bool showSuggestionsPopup() const { return checkBox_5->isChecked(); }

  /**
   * Checks if a pop-up message should be shown in the system tray. If @c true
   * it will, otherwise not.
   *
   * Default value is @c false.
   *
   * @image html show_systray_popup.png "The show system tray pop-up option"
   * @image html systray_popup.png "Kisa system tray pop-up"
   *
   * @return the current value
   */
  bool showSystrayPopup() const { return checkBox_8->isChecked(); }

  /**
   * Checks if the main window should be kept above other windows. If @c true,
   * then the main window will stay on top any other window on the desktop,
   * otherwise not.
   *
   * Default is @c true.
   *
   * @image html stay_on_top.png "The stay on top option"
   *
   * @return the current value
   */
  bool stayOnTop() const { return checkBox_12->isChecked(); }

  /**
   * Gets the value of the member variable.
   *
   * @note the pop-up will disappear after the given amount of seconds, even
   * if there is user interaction (such as scrolling the suggestion list).
   *
   * @return the current value in s
   */
  int suggestionsPopupDuration() const { return spinBox_3->value(); }

  /**
   * Gets the duration in s for showing the system tray pop-up.
   *
   * Default value is 5 s.
   *
   * @return the current value in s
   */
  int systrayPopupDuration() const { return spinBox_2->value(); }

  /**
   * Checks if to change the dictionary language whenever the keyboard input
   * layout changes. If @c true an attempt to match the new layout will be
   * made, otherwise the same dictionary will be used no matter what the
   * current layout is.
   *
   * @image html change_on_keyboard_layout.png "The change dictionary on keyboard layout change option"
   *
   * Default is @c false.
   *
   * @return the current value
   *
   * @bug see KisaLib::getKeyboardInputLayout()
   * @see KisaLib::getKeyboardInputLayout()
   */
  bool updateOnNewLayout() const { return checkBox_10->isChecked(); }

  public slots:

  /**
   * Adds an item to the ignore list. Items that are in the list are used
   * to create a regular expression string of window names to ignore when
   * subscribing to windows.
   *
   * @see ignoreList()
   */
  void addIgnoreListItem();

  /**
   * Gets the country flag icon of the current dictionary language used.
   *
   * @return the current country flag icon
   */
  QIcon currentCountryFlag() const {
    return comboBox_2->itemIcon(comboBox_2->currentIndex());
  }

  /**
   * Gets the country flag for the dictionary at the given index location.
   *
   * @return
   */
  QIcon countryFlag(const int index) const {
    return comboBox_2->itemIcon(index);
  }

  /**
   * Checks whether to treat hyphens as a punctuation. If @c true then
   * spellcheck will occur for each conjoined word. If @c false then the
   * entire word will be spellchecked.
   *
   * Default is @c false.
   *
   * @note Only one word will be visible at the time though.
   *
   * @image html hyphen_as_punctuation.png "The treat hyphen as punctuation option"
   */
  bool hyphenAsPunctuation() const { return checkBox_15->isChecked(); }

  /**
   * Reads the values from the application configuration file given by the
   * file @p fileName. If no file name is given the organization and
   * application name in lower case will determine the directory and file name.
   * This is set in Kisa::Kisa(), which will result in
   * "~/.config/kisa/kisa.conf".
   *
   * @note this reads only the settings from the settings window.
   *
   * @note QSettings::IniFormat is used.
   *
   * @note the default file name will be in lower case
   *
   * @param fileName the file to read settings from
   */
  void readSettings(QString fileName = QString());

  /**
   * Removes an Item from the Ignore List. Items that are in the list are used
   * to create a regular expression string of window names to ignore when
   * subscribing to windows.
   *
   * @see ignoreList()
   */
  void removeIgnoreListItem();

  /**
   * Gets the visibility state information since last time the application was
   * closed and uses that as a recommendation when starting.
   *
   * @return @c true if the application was closed in a visible state, @ false
   * otherwise
   */
  bool closedVisible() { return m_closedVisible; }

  /**
   * Writes the values to the application configuration file given by the
   * file @p fileName. If no file name is given the organization and
   * application name in lower case will determine the directory and file name.
   * This is set in Kisa::Kisa(), which will result in
   * "~/.config/kisa/kisa.conf".
   *
   * @note this saves only the settings from the settings window.
   *
   * @note QSettings::IniFormat is used.
   *
   * @note the default file name will be in lower case
   *
   * @param fileName the file to write settings to
   */
  void writeSettings(QString fileName = QString());

  private slots:

  /**
   * Opens up a file dialog whenever the custom command icon button is
   * clicked.
   *
   * @see customCommandIcon
   *
   * @image html icon_file_dialog.png "The file dialog when selecting a custom command icon"
   */
  void updateCustomCommandIcon();

  /**
   * Fills the combo box in the settings window with all the available
   * dictionaries. A country flag representing the language of the dictionary
   * will be displayed if the setting "show country flag" is set.
   *
   * @note Qt's locale system is used in order to make a best match for the
   * country given the language. This might not always be accurate as there
   * are languages that are spoken in several countries.
   *
   * @image html dictionaries.png "The available dictionaries installed on the system"
   */
  void updateDictionariesComboBox();

  private:

  /**
   * Creates a QStringList representation containing the Ignore List items.
   * Items that are in the list are used to create a regular expression string
   * of window names to ignore when subscribing to windows.
   *
   * @see createRegExpString
   * @see ignoreListRegExp
   * @return the list containing the items as strings.
   */
  const QStringList createIgnoreList();

  /**
   * Pointer to the library object.
   */
  KisaLib* kisaLib;

  /**
   * The font used to display text in the main window. This is by default set
   * to "Sans Serif".
   */
  QFont m_font;

  /**
   * The custom command icon.
   */
  QString m_iconFileName;

  /**
   * A string list representation of the Ignore list. Items that are in the
   * list are used to create a regular expression string of window names to
   * ignore when subscribing to windows.
   * Default list contains "("kickoff", "kwin", "toolbar")".
   */
  QStringList m_ignoreList;

  /**
   * Stores the visibility state of the application since last close.
   */
  bool m_closedVisible;
};

#endif
